`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Arizona State University
// Engineers: Brentton Garber, Georgii Tkachuk
// 
// Create Date: 17:28:56 05/01/2013 
// Design Name: register_set
// Module Name: register_set
// Project Name: Lab 3
// Target Devices: Xilinx Spartan6 XC6LX16-CS324 
// Tool versions: Xilinx ISE 14.2 
// Description: Stores data into four individual registers, (A,B,C,D). Gives data to the ALU,
//					 then stores its output. Also gives register values to the display.
//
// Revision: 1
// Revision 0.01 - File Created
//
//////////////////////////////////////////////////////////////////////////////////
module register_set(
	input [3:0]data, 
	input [1:0]addr,
	input LDR,
	input dis_read,
	input [1:0]dis_addr,
	input reset,
	input clk,
	input alu_en,
	input [7:0]ALU_data,
	output [3:0]rega,
	output [3:0]regb,
	output reg [3:0]dis_data);

// Define our registers
reg [3:0]reg_set[0:3];
reg [3:0]mem[0:3];
reg [3:0]alumem[0:3];

//feed data at registers specified in srcAsel and srcBsel to ALU 
assign rega = alumem[data[3:2]];
assign regb = alumem[data[1:0]];

assign alu_greater = (ALU_data > 8'b0000_1111)? 1'b1: 1'b0;
//sending requested data to the segment display. segment display has to be reworked. 
always @(*) begin
	if(dis_read)
		dis_data = mem[dis_addr];
	else
		dis_data = 4'b0000;
end

// Always on posedge of clock
always @(posedge clk or negedge reset) begin
	if (~reset) begin
		reg_set[0] <= 0;
		reg_set[1] <= 0;
		reg_set[2] <= 0;
		reg_set[3] <= 0;
	end
	else begin
		if(alu_en) begin // if the ALU is enabled
			if(alu_greater) // if the ALU data is greater, use bits 4-7
				reg_set[addr] <= ALU_data[7:4];
			else // if the ALU data is smaller, use bits 0-3
				reg_set[addr] <= ALU_data[3:0];
		end
		else if(LDR) // if LDR, write data to the register from decoder
			reg_set[addr] <= data;
	end //else 
end //end always 

// At positive edge of clock, write data from mem to the alu mem
always @(posedge clk) begin
	alumem[0] <= mem[0];
	alumem[1] <= mem[1];
	alumem[2] <= mem[2];
	alumem[3] <= mem[3];
end	
			
// At positive edge of clock, write data from reg_set to the mem
always @(posedge clk) begin
	if(~alu_en) begin
		mem[0] <= reg_set[0];
		mem[1] <= reg_set[1];
		mem[2] <= reg_set[2];
		mem[3] <= reg_set[3];
	end
end

endmodule
